#pragma once
#include <iostream>
#include <memory>
#include <sys/epoll.h>

#include "Connection.hpp"//#include "Connection.hpp"
#include "Socket.hpp" //#include "InetAddr.hpp"
#include "Channel.hpp"
#include "Reactor.hpp"
using namespace SocketModule;
//继承时要指定访问限定符
class Listener : public Connection{
public:
    Listener(int port = 8080)
    :_port(port),
     _listensock(std::make_unique<TcpSocket>())
    {
        //一键构建套接字对象
        _listensock->BuildTcpServerSocketMethod(_port);
        //设置成非阻塞模式
        SetNonBlock(_listensock->FD());
        //因为这里是链接管理器所以只需要读取链接就可以了,且设置成ET模式
        SetEvent(EPOLLIN | EPOLLET);

    }

    void Recver() override
    {
        Inet_Addr addr;
        while(true)
        {
            //Listener只处理读即可因为他只管理链接accept了
            int sockfd = _listensock->Accept(&addr);
            //无论是底层无连接,还是accept出错都直接退出
            if(sockfd == ACCEPT_ERR || sockfd== ACCEPT_DONE)
            {
                break;
            }
            //还有链接未读取完继续读取
            if(sockfd == ACCEPT_CONTINUE)
            {
                continue;
            }

            //成功读取到文件描述符
            //创建一个套接字的管理对象
            std::shared_ptr<Connection> conn = std::make_shared<Channel>(sockfd, addr);

            //将回调函数注册给新的套接字对象
            conn->RegiserHandler(_handler);
            //利用回指指针将套接字对象交给Reactor进行管理
            GetOwner()->AddConnection(conn);
            
        }
        
    }
    int GetFd() override
    {
        return _listensock->FD();
    }
    void Sender() override
    {

    }
    void Excepter() override
    {

    }
private:
    int _port;
    std::unique_ptr<Socket> _listensock;//TCP套接字对象
};